// The background page is asking us to find an address on the page.
if (window == top) {
  chrome.extension.onRequest.addListener(function(req, sender, sendResponse) {
    sendResponse(findAddress());
  });
}

var isCtrl = false;

var handler;
var topHandler;

jQuery.fn.isNews = function() {
  return jQuery("li.w0 a:first", this).length > 0;
}

jQuery.fn.isVideos = function() {
  return this.hasClass("videobox");
}

jQuery.fn.isImages = function() {
  return this.attr("id") === "imagebox";
}

jQuery.fn.isMaps = function() {
  return $("div.ibk:first", this).length > 0;
}

jQuery.fn.isSitelinks = function() {
  return $("table.slk:first", this).length > 0;
}

function SitelinkItems(prevItem) {
	var items =  [];  
	var itemIndex = 0;	
	var half;
	
	var prevLevel = function() {
		handler = prevItem;
		handler.gotoItem(0);
	}

	var nextLevel = function() {
		handler = prevItem;
		handler.gotoItem(1);
	}
	
	var create = function() {
		items = $("a.sla", prevItem.getCurrentItem())
		half = items.length / 2;
		return $.map(items, function(element) {return $(element)});
	}
	
	var getCurrentItem = function() {
		if (itemIndex < 0) {
			itemIndex = items.length - 1;
		} else if (itemIndex >= items.length) {
			itemIndex = 0;
		}
    
		return items[itemIndex];
	}

	this.gotoItem = function(offset) {
		var focus = function() {
			getCurrentItem().focus();
		}
    
		if (items.length == 0) {
			items = create();
		} else {
			itemIndex += offset;
		}
  
		focus()
	}

	this.left = function() {		
		if (itemIndex >= half) {
			this.gotoItem(-half);
		} else {
			handler = prevItem;
			handler.gotoItem(0)					
		}
	}
  
	this.right = function() {
		if (itemIndex < half) {
			this.gotoItem(half);
		}
	}
  
	this.up = function() {
		if (itemIndex == 0 || itemIndex == half) {
			handler = prevItem;
			handler.gotoItem(0)			
		} else {
			this.gotoItem(-1);
		}		
	}
  
	this.down = function() {
		if (itemIndex == half - 1 || itemIndex == items.length - 1) {
			handler = prevItem;
			handler.gotoItem(1)
		} else {
			this.gotoItem(1);
		}		
	}	
}

function MapItems(prevItem) {
	var items =  [];  
	var itemIndex = 0;	
	
	var prevLevel = function() {
		handler = prevItem;
		handler.gotoItem(0);
	}

	var nextLevel = function() {
		handler = prevItem;
		handler.gotoItem(1);
	}

	var create = function() {
		items = $("div.s a", prevItem.getCurrentItem())
		return $.map(items, function(element) {return $(element)});
	}
  
	var getCurrentItem = function() {
		if (itemIndex < 0) {
			itemIndex = items.length - 1;
		} else if (itemIndex >= items.length) {
			itemIndex = 0;
		}
    
		return items[itemIndex];
	}

	this.gotoItem = function(offset) {
		var focus = function() {
			getCurrentItem().focus();
		}
    
		if (items.length == 0) {
			items = create();
		} else {
			itemIndex += offset;
		}
  
		focus()
	}
  
	this.left = function() {
		this.gotoItem(-1);
	}
  
	this.right = function() {
		this.gotoItem(1);
	}
  
	this.up = function() {
		handler = prevItem;
		handler.gotoItem(0)
	}
  
	this.down = function() {
		handler = prevItem;
		handler.gotoItem(1)
	}	
}

function ImageItems(prevItem) {
	var items =  [];  
	var itemIndex = 0;	
	
	var prevLevel = function() {
		handler = prevItem;
		handler.gotoItem(0);
	}

	var nextLevel = function() {
		handler = prevItem;
		handler.gotoItem(1);
	}

	var getCurrentItem = function() {
		if (itemIndex < 0) {
			itemIndex = items.length - 1;
		} else if (itemIndex >= items.length) {
			itemIndex = 0;
		}
    
		return items[itemIndex];
	}
		
	var absGotoItem = function(index) {
		focus = function() {
			getCurrentItem().parent().focus();
		}
		
		itemIndex = index;
		focus()
	}
  
	create = function() {    		
		function flowGraph(items) {
			function centers() {
				function center(element) {
					offset = element.offset();
					return {cx: (offset.left + element.width()) / 2, cy: (offset.top + element.height()) / 2, left: offset.left, right: offset.left + element.width(),  top: offset.top, bottom: offset.top + element.height()};
				}
				return $.map(items, center);
			}
			
			itemsCenters = centers();

			function neighbors(index, item) {      
				function find(dir, negDir, condition, onNotFound) {
					minDist = 999999;
					found = false;
					$.each(items, 
						function(currentIndex) {
							if (currentIndex == index) {
								return;
							}
				  
							x = itemsCenters[currentIndex].cx - itemsCenters[index].cx;
							y = itemsCenters[currentIndex].cy - itemsCenters[index].cy;
				  
							dist = x*x+y*y;
							if (dist < minDist && condition(currentIndex)) {
								minDist = dist;
								found = true;
								item.data(dir, currentIndex);               
							}
						}
					);
			  
					if (found === false) {
						item.data(dir, -1);
						item.data(dir+"Default", onNotFound);
					}
				}
			
				function isRightCanidate(currentIndex) {        
					return itemsCenters[currentIndex].left > itemsCenters[index].right
				}

				function isLeftCanidate(currentIndex) {
					return itemsCenters[currentIndex].right < itemsCenters[index].left
				}

				function isDownCanidate(currentIndex) {
					return itemsCenters[currentIndex].top >= itemsCenters[index].bottom;
				}

				function isUpCanidate(currentIndex) {
					return itemsCenters[currentIndex].bottom <= itemsCenters[index].top;
				}

				find("right", "left", isRightCanidate, focus);
				find("down", "up", isDownCanidate, nextLevel);
				find("left", "right", isLeftCanidate, focus);
				find("up", "down", isUpCanidate, prevLevel);
			
				function printDir(dir) {
					return " " + dir + ": " + item.data(dir);
				}
			
				console.log("item " + index + " ->" + printDir("right") + printDir("down")  + printDir("left") + printDir("up"));
			}        
		  
			$.each(items, neighbors);
		}  
		
		items = $("img", prevItem.getCurrentItem())
		items = $.map(items, function(item) {return $(item)});		
		flowGraph(items);		
	}
	
	this.gotoItem = function(offset) {
		if (items.length == 0) {
			create();
		} else {
			itemIndex += offset;
		}
  
		absGotoItem(itemIndex);
	}
  
	handleDirection = function(dir) {
		item = getCurrentItem();
		index = item.data(dir);
		if (index >= 0) {      
			absGotoItem(index);
		} else if (index === -1) {
			item.data(dir+"Default")();
		}
	}
  
	this.left = function() {
		handleDirection("left");    
	}
  
	this.right = function() {
		handleDirection("right");
	}
  
	this.up = function() {
		handleDirection("up");
	}
  
	this.down = function() {
		handleDirection("down");
	}  
}

function VideoItems(prevItem) {
  var items =  [];
  var itemIndex = 0;

  var create = function() {
    items = $("td a", prevItem.getCurrentItem())
    return $.map(
      items, 
      function(element, index) {
        if ((index % 2) === 1) {
          return element;
        } else {
          return null;
        }
      });
  }

  getCurrentItem = function() {
    if (itemIndex < 0) {
      itemIndex = items.length - 1;
    } else if (itemIndex >= items.length) {
      itemIndex = 0;
    }
    
    return items[itemIndex];
  }

  this.gotoItem = function(offset) {
	var focus = function() {
		getCurrentItem().focus();
	}
    
	if (items.length == 0) {
      items = create();
    } else {
      itemIndex += offset;
    }
  
    focus()
  }
  
  this.left = function() {
    this.gotoItem(-1);
  }
  
  this.right = function() {
    this.gotoItem(1);
  }
  
  this.up = function() {
    handler = prevItem;
    handler.gotoItem(0)
  }
  
  this.down = function() {
    handler = prevItem;
    handler.gotoItem(1)
  }
}

function NewsItems(prevItem) {
  var items =  [];
  var itemIndex = 0;
    
  var create = function() {
    return $("a:first", $("li.w0", prevItem.getCurrentItem()))
  }

  var getCurrentItem = function() {
    if (itemIndex < 0) {
      itemIndex = items.length - 1;
    } else if (itemIndex >= items.length) {
      itemIndex = 0;
    }
    
    return items[itemIndex];
  }

  this.gotoItem = function(offset) {
	var focus = function() {
		getCurrentItem().focus();
	}
    
	if (items.length == 0) {
      items = create();
    } else {
      itemIndex += offset;
    }
  
    focus()
  }
    
  this.left = function() {
    handler = prevItem;
    handler.gotoItem(0)
  }
  
  this.right = function() {
  }
  
  this.up = function() {
    if (itemIndex == 0) {
		handler = prevItem;
		handler.gotoItem(0);
		return;
	}
	
	this.gotoItem(-1);
  }
  
  this.down = function() {
    if (itemIndex == items.length - 1) {
		handler = prevItem;
		handler.gotoItem(1)	;
		return;
	}

	this.gotoItem(1);
  }
}

function focusSearch() {
	$('input[name="q"]').focus();
	itemIndex = -1;
	handler = null;
	topHandler = null;
}

function TopLevelItem() {
	a_items =  [];
	li_items =  [];
	itemIndex = 0;
  
	var arrow = $("<span>&rArr;</span>");
	
	create = function() {
		li_create = function() {
			return $("li.g");
		}

		li_items = li_create();
		a_items =  $(":visible a:first", li_items);
		li_items = $.map(li_items, function(item) {return $(item)});
		a_items = $.map(a_items, function(item) {return $(item)});
		li_items[0].data("checked", true);
	}
   
	getItem = function(items) {
		wrapItem = function() {
			if (itemIndex < 0) {
				itemIndex = 0;				
			} else if (itemIndex >= items.length) {
				itemIndex = 0;
			}  
		}
    
		wrapItem();
    
		return items[itemIndex];
	}
  
	getLinkItem = function() {
		return getItem(a_items);
	}
  
	this.gotoItem = function(offset) {					
		focus = function() {
			getLinkItem().focus();
		}
		
		if (a_items.length == 0 || a_items[0] == null) {      
			create();
			itemIndex = 0;
		} else {
			itemIndex += offset;
		}
  	
		arrow.remove();
		focus();
		
		item = this.getCurrentItem();
		subFactory = item.data("subFactory")
		
		if (item.data("subFactory") == null) {
			subFactory = null;
			if (item.isNews()) {
				subFactory = NewsItems;
			} else if (item.isVideos()) {
				subFactory = VideoItems;
			} else if (item.isImages()) {
				subFactory = ImageItems;
			} else if (item.isMaps()) {
				subFactory = MapItems;
			}  else if (item.isSitelinks()) {
				subFactory = SitelinkItems;
			}
			
			if (subFactory !== null) {							
				item.data("subFactory", subFactory);
			} else {
				item.data("subFactory", "");
			}
		}
		
		if (subFactory != null && subFactory != "") {
			getLinkItem().append(arrow);
		}
	}
    
	this.isValid = function() {
		if (li_items.length == 0) {
			return true;
		}
		
		return $("li.g:first").data("checked") === true;
	}
	
	this.getCurrentItem = function() {
		return getItem(li_items);
	}
  
	this.left = function() {

	}
  
	this.right = function() {
		item = this.getCurrentItem();
		sub = item.data("sub")
		if (sub != "") {
			if (sub == null) {
				subFactory = item.data("subFactory")
		
				if (subFactory !== null && subFactory !== "") {
					handler = new subFactory(handler);
					item.data("sub", handler);
				} else {
					item.data("sub", "");
				}
			} else {
				handler = sub;
			}
		}
    
		handler.gotoItem(0);
	}
  
	this.up = function() {
		if (itemIndex == 0) {
			focusSearch()
			return;
		}
		
		this.gotoItem(-1);
	}
  
	this.down = function() {
		this.gotoItem(1);
	}
}

function registerKeyUp() {

  function checkPageUpdate() {
	if (topHandler != null && topHandler.isValid()) {
		return;
	}
	
	handler = new TopLevelItem();
	topHandler = handler;
  }
  
  function onKeyUp() {
    checkPageUpdate();
	handler.up();
  }

  function onKeyDown() {
	checkPageUpdate();
	handler.down();
  }

  function onKeyLeft() {
    checkPageUpdate();
	handler.left();
  }

  function onKeyRight() {
    checkPageUpdate();
	handler.right();
  }
  
  $(document).keyup(function (e) {
    if(e.which == 17) isCtrl=false;
  }).keydown(function (e) {
    if(e.which == 17) isCtrl=true;
  });

  $(document).keyup(function(e) {
	if (e.which == 191)  {
		focusSearch();
		return false;
	} else if (isCtrl) {
		if (e.which == 40) onKeyDown()
		else if (e.which == 38) onKeyUp()
		else if (e.which == 39) onKeyRight()
		else if (e.which == 37) onKeyLeft()
	}
	
	return true;
  });
}

$(document).ready(registerKeyUp);